package com.epam.traning.taskmanager.xml;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import android.content.Context;
import android.content.res.Resources.NotFoundException;

public class XmlParser {

	private static XmlParser instance;
	
	private XmlParser() {
		
	}
	
	public static XmlParser getInstance() {
		if (instance == null) {
			instance = new XmlParser();
		}
		return instance;
	}
	
	public void parse(Context ctx, int rawResource, final IXmlHandler xmlHandler) throws SAXException, NotFoundException, IOException, ParserConfigurationException {
		InputStream is = ctx.getResources().openRawResource(rawResource);
		parse(ctx, is, xmlHandler);
	}
	
	public void parse(Context ctx, InputStream is, final IXmlHandler xmlHandler) throws SAXException, NotFoundException, IOException, ParserConfigurationException {
		final SAXParserFactory factory = SAXParserFactory.newInstance();
        final SAXParser xml = factory.newSAXParser();
        XMLReader xmlReader = xml.getXMLReader();
        xmlReader.setContentHandler(new ContentHandler() {
			
        	private StringBuffer mBuffer = new StringBuffer();
        	
			@Override
			public void startPrefixMapping(String prefix, String uri)
					throws SAXException {
			}
			
			@Override
			public void startElement(String uri, String localName, String qName,
					Attributes atts) throws SAXException {
				mBuffer.setLength(0);
				xmlHandler.startTag(localName, atts);
			}
			
			@Override
			public void startDocument() throws SAXException {
				xmlHandler.startDocument();
			}
			
			@Override
			public void skippedEntity(String name) throws SAXException {
			}
			
			@Override
			public void setDocumentLocator(Locator locator) {
			}
			
			@Override
			public void processingInstruction(String target, String data)
					throws SAXException {
			}
			
			@Override
			public void ignorableWhitespace(char[] ch, int start, int length)
					throws SAXException {
			}
			
			@Override
			public void endPrefixMapping(String prefix) throws SAXException {
			}
			
			@Override
			public void endElement(String uri, String localName, String qName)
					throws SAXException {
				xmlHandler.endTag(localName, mBuffer.toString());
			}
			
			@Override
			public void endDocument() throws SAXException {
			}
			
			@Override
			public void characters(char[] ch, int start, int length)
					throws SAXException {
				String chars = new String(ch, start, length); 
				mBuffer.append(chars.trim());
			}
		});
		xmlReader.parse(new InputSource(is));
	}
	
	/**
	 * Interface, which used for parse xml.
	 * 
	 * @author Uladzimir Klyshevich
	 *
	 */
	public interface IXmlHandler<T> {

		/**
		 * Call if document start.
		 */
		void startDocument();

		/**
		 * Call if tag start.
		 * @param name tag name
		 * @param xml xml pull parser
		 */
		void startTag(String name, Attributes atts);

		/**
		 * Call if tag end.
		 * @param name tag
		 * @param value
		 */
		void endTag(String name, String value);

		/**
		 * Gets result after parsing.
		 * @return result object
		 */
		T getResult();
	}
}
